<?php
/*
---------------------------------------------------------------------------
backend.php for SALAM

Copyright 2009, 2010 Jacob McEntire

    This file is part of SALAM.

    SALAM is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    SALAM is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with SALAM.  If not, see <http://www.gnu.org/licenses/>.
---------------------------------------------------------------------------
*/

//Get User Settings
require('settings.php');
//Set Timezone
date_default_timezone_set($time_zone);

//Database Configuration and Function to Connect to DB:
function opendb(){
	global $conn, $dbhost, $dbuser, $dbpass, $dbname;
	$conn = mysql_connect($dbhost, $dbuser, $dbpass) or die ('Error connecting to mysql');
	mysql_select_db($dbname);
}

//Close the DB
function closedb(){
	global $conn;
	mysql_close($conn);
}

//Run a query on the DB
function run_query($query) {
    opendb();
    $result = mysql_query($query) or die('Error, query failed ' . mysql_error());
    closedb();
    return $result;
}

function run_query_return_id($query) {
    opendb();
    $result = mysql_query($query) or die('Error, query failed ' . mysql_error());
	$id = mysql_insert_id();
    closedb();
    return $id;
}

function return_state($value) {
	switch ($value) {
		case 0:
			return 'OK';
			break;
		case 1:
			return 'Warning';
			break;
		case 2:
			return 'Critical';
			break;
		default:
			return 'Error';
			break;
	}
}

function run_trigger($frequency) {
	$time = time();
	run_query("REPLACE INTO run_times (frequency, last_run) VALUES ('$frequency', '$time')");
	global $from_email, $to_email, $install_dir, $email_start, $email_end;
	$email_start = mktime($email_start, 0, 0);
	$email_end = mktime($email_end, 0, 0);
	if ($time >= $email_start && $time <= $email_end)
		$between_times = TRUE;
	else
		$between_times = FALSE;
	//Get all hosts/triggers/checks for the $frequency specified
	$result = run_query("SELECT triggers.id, triggers.name, triggers.arguments, triggers.send_warning_email, triggers.send_critical_email, checks.file_name, checks.host_arg, checks.data_names, checks.data_types, hosts.id, hosts.name, hosts.dns_name_or_ip, hosts_triggers.uptime, hosts_triggers.warningtime, hosts_triggers.criticaltime, hosts_triggers.last_check, locations.name, groups.name FROM triggers, checks, hosts, hosts_triggers, locations, groups WHERE triggers.frequency = '$frequency' AND triggers.check_id = checks.id AND triggers.id = hosts_triggers.trigger_id AND hosts_triggers.host_id = hosts.id AND hosts.location_id = locations.id AND hosts.group_id = groups.id AND hosts.enable_monitoring = 1");
	if (mysql_num_rows($result) != NULL){
		while(list($trigger_id, $trigger_name, $trigger_arguments, $send_warning_email, $send_critical_email, $check_file, $host_arg, $data_names, $data_types, $host_id, $host_name, $dns_name_or_ip, $uptime, $warningtime, $criticaltime, $last_check, $location, $group) = mysql_fetch_array($result)) {
			//Create $cmd to run, run, then return and parse data
			$cmd = $install_dir . $check_file . ' ' . $host_arg . ' ' . $dns_name_or_ip . ' ' . $trigger_arguments;
			exec($cmd,$data,$return_code);
			list($info, $data) = explode("|", $data[0]);
			$data = explode(" ", $data);
			foreach ($data as $key => $value)
				$data[$key] = explode(";", $value);
			$trig_data = NULL;
			foreach ($data as $key => $value) {
				$trig_data[$key] = preg_replace("/[^0-9.]/", '', $value[0]);
			}
			$data_names = explode("|", $data_names);
			$data_types = explode("|", $data_types);
			foreach ($trig_data as $key => $value) {
				if ($key == 0)
					$data = $data_names[$key] . '=' . $value . $data_types[$key];
				else
					$data .= '|' . $data_names[$key] . '=' . $value . $data_types[$key];
			}
			$time = time();
			$send_email = FALSE;
			$force_send_email = FALSE;
			//Are there active alerts for this host and trigger
			$alert_result = run_query("SELECT id, type, email_sent FROM alerts WHERE host_id = $host_id AND trigger_id = $trigger_id AND active = 1 LIMIT 1");
			if (mysql_num_rows($alert_result) == NULL) {
				if ($return_code != 0) {
					//Add alert to the alerts table
					$alert_id = run_query_return_id("INSERT INTO alerts (host_id, trigger_id, active, type, start_time, last_check, email_sent, current_info, current_data) VALUES ('$host_id', '$trigger_id', 1, '$return_code', '$time', '$time', 0, '$info', '$data')");
					$send_email = TRUE;
				}
			}
			else {
				list($alert_id, $alert_type, $email_sent) = mysql_fetch_array($alert_result);
				if ($return_code == 0) {
					run_query("UPDATE alerts SET active = 0, last_check = '$time' WHERE id = '$alert_id'");
					if ($email_sent != 0)
						$force_send_email = TRUE;
				}
				else {
					if ($return_code == $alert_type) {
						//Update existing alert with current information
						run_query("UPDATE alerts SET last_check = '$time', current_info = '$info', current_data = '$data' WHERE id = '$alert_id'");
						if ($email_sent == 0)
							$send_email = TRUE;
					}
					else {
						run_query("UPDATE alerts SET active = 0, last_check = '$time' WHERE id = '$alert_id'");
						$alert_id = run_query_return_id("INSERT INTO alerts (host_id, trigger_id, active, type, start_time, last_check, email_sent, current_info, current_data) VALUES ('$host_id', '$trigger_id', 1, '$return_code', '$time', '$time', 0, '$info', '$data')");
						if ($email_sent != 0)
							$force_send_email = TRUE;
						else
							$send_email = TRUE;
					}
				}
			}
			//See if we need to send an email
			if ($return_code == 0 && $force_send_email == TRUE)
				$recovery_email[] = array('state' => $return_code, 'host' => $host_name, 'ip' => $dns_name_or_ip, 'trigger' => $trigger_name, 'location' => $location, 'group' => $group, 'info' => $info, 'data' => $data, 'time' => $time, 'alert_id' => $alert_id);
			elseif ($return_code == 1 && (($send_email == TRUE && $send_warning_email == 1 && $between_times == TRUE) || $force_send_email == TRUE))
				$warning_email[] = array('state' => $return_code, 'host' => $host_name, 'ip' => $dns_name_or_ip, 'trigger' => $trigger_name, 'location' => $location, 'group' => $group, 'info' => $info, 'data' => $data, 'time' => $time, 'alert_id' => $alert_id);
			elseif ($return_code > 1 && (($send_email == TRUE && $send_critical_email == 1 && $between_times == TRUE) || $force_send_email == TRUE))
				$critical_email[] = array('state' => $return_code, 'host' => $host_name, 'ip' => $dns_name_or_ip, 'trigger' => $trigger_name, 'location' => $location, 'group' => $group, 'info' => $info, 'data' => $data, 'time' => $time, 'alert_id' => $alert_id);

			//Update hosts_triggers table with uptime and current data
			switch ($return_code) {
				case 3:
				case 2:
					if ($last_check != 0)
						$criticaltime += ($time - $last_check);
					run_query("UPDATE hosts_triggers SET criticaltime = '$criticaltime', last_check = '$time', current_state = '$return_code', current_info = '$info', current_data = '$data' WHERE host_id = '$host_id' AND trigger_id = '$trigger_id'");
					break;
				case 1:
					if ($last_check != 0)
						$warningtime += ($time - $last_check);
					run_query("UPDATE hosts_triggers SET warningtime = '$warningtime', last_check = '$time', current_state = '$return_code', current_info = '$info', current_data = '$data' WHERE host_id = '$host_id' AND trigger_id = '$trigger_id'");
					break;
				case 0:
					if ($last_check != 0)
						$uptime += ($time - $last_check);
					run_query("UPDATE hosts_triggers SET uptime = '$uptime', last_check = '$time', current_state = '$return_code', current_info = '$info', current_data = '$data' WHERE host_id = '$host_id' AND trigger_id = '$trigger_id'");
					break;
			}
			//Insert trigger results into trigger_data table
			foreach ($trig_data as $key => $value) {
				if ($key == 0)
					$data = $value;
				else
					$data .= '|' . $value;
			}
			run_query("INSERT INTO trigger_data (trigger_id, host_id, time, state, data) VALUES ('$trigger_id', '$host_id', '$time', '$return_code', '$data')");
		}
	}
	//Send any emails we need to
	$headers = 'From: ' . $from_email;
	$critical_count = count($critical_email);
	if ($critical_count > 0) {
		$message = '';
		if ($critical_count == 1)
			$subject = return_state($critical_email[0]['state']) . ':' . $critical_email[0]['host'] . ' - ' . $critical_email[0]['trigger'];
		else
			$subject = 'Critical:Multiple Triggers';
		$first_row = TRUE;
		foreach ($critical_email as $value) {
			$message .= 'Date/Time: ' . date("D M j G:i:s T Y", $value['time']) . "\n" . 'Host: ' . $value['host'] . "\n" . 'Location: ' . $value['location'] . "\n" . 'Group: ' . $value['group'] . "\n" . 'HostName/IP: ' . $value['ip'] . "\n" . 'Trigger: ' . $value['trigger'] . "\n" . 'State: ' . return_state($value['state']) . "\n" . 'Info: ' . $value['info'] . "\r\n" . ' Data: ' . "\n";
			$data = explode("|", $value['data']);
			foreach ($data as $i)
				$message .= $i . "\n";
			$message .= "\r\n \r\n";
			if ($first_row == TRUE) {
				$query_ids = "id = '" . $value['alert_id'] . "'";
				$first_row = FALSE;
			}
			else
				$query_ids .= " OR id = '" . $value['alert_id'] . "'";
		}
		$status = mail($to_email, $subject, $message, $headers);
		if ($status == TRUE) {
			$email_sent = time();
			$query = "UPDATE alerts SET email_sent = '$email_sent' WHERE " . $query_ids;
			run_query($query);
		}
	}
	$warning_count = count($warning_email);
	if ($warning_count > 0) {
		$message = '';
		if ($warning_count == 1)
			$subject = return_state($warning_email[0]['state']) . ':' . $warning_email[0]['host'] . ' - ' . $warning_email[0]['trigger'];
		else
			$subject = 'Warning:Multiple Triggers';
		$first_row = TRUE;
		foreach ($warning_email as $value) {
			$message .= 'Date/Time: ' . date("D M j G:i:s T Y", $value['time']) . "\n" . 'Host: ' . $value['host'] . "\n" . 'Location: ' . $value['location'] . "\n" . 'Group: ' . $value['group'] . "\n" . 'HostName/IP: ' . $value['ip'] . "\n" . 'Trigger: ' . $value['trigger'] . "\n" . 'State: ' . return_state($value['state']) . "\n" . 'Info: ' . $value['info'] . "\r\n" . ' Data: ' . "\n";
			$data = explode("|", $value['data']);
			foreach ($data as $i)
				$message .= $i . "\n";
			$message .= "\r\n \r\n";
			if ($first_row == TRUE) {
				$query_ids = "id = '" . $value['alert_id'] . "'";
				$first_row = FALSE;
			}
			else
				$query_ids .= " OR id = '" . $value['alert_id'] . "'";
		}
		$status = mail($to_email, $subject, $message, $headers);
		if ($status == TRUE) {
			$email_sent = time();
			$query = "UPDATE alerts SET email_sent = '$email_sent' WHERE " . $query_ids;
			run_query($query);
		}
	}
	$recovery_count = count($recovery_email);
	if ($recovery_count > 0) {
		$message = '';
		if ($recovery_count == 1)
			$subject = 'Recovery:' . $recovery_email[0]['host'] . ' - ' . $recovery_email[0]['trigger'] . ' ' . return_state($recovery_email[0]['state']);
		else
			$subject = 'Recovery:Multiple Triggers';
		$first_row = TRUE;
		foreach ($recovery_email as $value) {
			$message .= 'Date/Time: ' . date("D M j G:i:s T Y", $value['time']) . "\n" . 'Host: ' . $value['host'] . "\n" . 'Location: ' . $value['location'] . "\n" . 'Group: ' . $value['group'] . "\n" . 'HostName/IP: ' . $value['ip'] . "\n" . 'Trigger: ' . $value['trigger'] . "\n" . 'State: ' . return_state($value['state']) . "\n" . 'Info: ' . $value['info'] . "\r\n" . ' Data: ' . "\n";
			$data = explode("|", $value['data']);
			foreach ($data as $i)
				$message .= $i . "\n";
			$message .= "\r\n \r\n";
			if ($first_row == TRUE) {
				$query_ids = "id = '" . $value['alert_id'] . "'";
				$first_row = FALSE;
			}
			else
				$query_ids .= " OR id = '" . $value['alert_id'] . "'";
		}
		$status = mail($to_email, $subject, $message, $headers);
		if ($status == TRUE) {
			$email_sent = time();
			$query = "UPDATE alerts SET email_sent = '$email_sent' WHERE " . $query_ids;
			run_query($query);
		}
	}
}

function run_maint() {
	global $keep_data, $keep_ratio;
	$end_clean = mktime(0, 0, 0, date("n"), (date("j") - $keep_data));
	$host_result = run_query("SELECT host_id, trigger_id from hosts_triggers");
	if (mysql_num_rows($host_result) != NULL) {
		while(list($host_id, $trigger_id) = mysql_fetch_array($host_result))	{
			$count_result = run_query("SELECT COUNT(id) AS numrows FROM trigger_data WHERE host_id = '$host_id' AND trigger_id = '$trigger_id' AND time < '$end_clean' AND state != 9 ORDER BY time ASC");
			list($numrows) = mysql_fetch_array($count_result);
			if (mysql_num_rows($count_result) == 1 && $numrows >= $keep_ratio) {				
				for ($offset = 0; $offset <= $numrows; $offset += $keep_ratio) {
					$data_result = run_query("SELECT data, time FROM trigger_data WHERE host_id = '$host_id' AND trigger_id = '$trigger_id' AND time < '$end_clean' AND state != 9 ORDER BY time ASC LIMIT $offset, $keep_ratio");
					if (mysql_num_rows($data_result) == $keep_ratio) {
						$rows = mysql_num_rows($data_result);
						$n = 0;
						$total_time = 0;
						$total_data = NULL;
						$average_data = NULL;
						$firstrow = TRUE;
						while(list($data, $time) = mysql_fetch_array($data_result)) {
							$n++;
							if ($firstrow == TRUE) {
								$min_time = $time;
								$firstrow = FALSE;
							}
							$max_time = $time;
							$total_time += $time;
							$data = explode("|", $data);
							foreach ($data as $key => $value)
								$total_data[$key] += $value;
						}
						foreach ($total_data as $key => $value) {
							if ($key == 0)
								$data = ($value / $n);
							else
								$data .= '|' . ($value / $n);
						}
						$insert_time = round($total_time / $n);
						$insert_result = run_query("INSERT INTO trigger_data (trigger_id, host_id, time, state, data) VALUES ('$trigger_id', '$host_id', '$insert_time', 9, '$data')");
						if ($insert_result == TRUE)
							$inserts[] = array(min_time => $min_time, max_time => $max_time);
					}
				}
				foreach ($inserts as $value) {
					run_query("DELETE FROM trigger_data WHERE host_id = '$host_id' AND trigger_id = '$trigger_id'  AND time BETWEEN '$value[min_time]' AND '$value[max_time]' AND state != 9");
				}
			}
		}
	}
	run_query("OPTIMIZE TABLE trigger_data");
}
?>
